#include "stdafx.h"

#include <oledbdm.h>

#include "DMAlgorithm.h"
#include "DMPluginServices.h"
#include "DMUtils.h"
using namespace PluginAlgorithms;
using namespace System::Globalization;



TaskProgressNotification^ ModelServices::CreateTaskNotification()
{
	return gcnew TaskProgressNotification(this);
}



TaskProgressNotification::TaskProgressNotification(ModelServices^ in_modelServices)
{
	m_jobID		=	0;
	m_timeStart = 0;

	currentValue	=	0;
	totalValue = 0;
	notificationFormat = String::Empty;
	modelServices = in_modelServices;
}

void TaskProgressNotification::Start()
{
	modelServices ->FireProgressNotification( this, DM_PROGRESS_NOTIFY_START, true);
}
void TaskProgressNotification::Progress()
{
	modelServices ->FireProgressNotification( this, DM_PROGRESS_NOTIFY_CURRENT, true);
}
void TaskProgressNotification::End(bool success)
{
	modelServices ->FireProgressNotification( this, DM_PROGRESS_NOTIFY_END, success);
}



void	ModelServices::EmitSingleTraceNotification( System::String^ text)
{
	EmitSingleTraceNotification(text, 0, 0);
}


void	ModelServices::EmitSingleTraceNotification( System::String^ stringFormat, System::Int64 currentValue, System::Int64 totalValue)
{
	DM_PROGRESS_NOTIFICATION_EVENT	progEvent;
	memset(&progEvent, 0, sizeof(progEvent)) ;
	BSTR	bstrTmp;
	
	try
	{
		System::String^	strText = System::String::Format( CultureInfo::InvariantCulture, stringFormat, currentValue, totalValue);

		progEvent.flags = DMPNF_USE_CCHTEXT;
		progEvent.NotifCode = DM_PROGRESS_NOTIFY_CURRENT;
		progEvent.nCurrent = (UINT)currentValue;
		progEvent.nTotal = (UINT)totalValue;
		
		bstrTmp	=	(BSTR)(void*)System::Runtime::InteropServices::Marshal::StringToBSTR( strText );
		progEvent.cchText = strText->Length;
		progEvent.pchText = bstrTmp;

		FireProgressNotification( progEvent );
	}
	finally
	{
		System::Runtime::InteropServices::Marshal::FreeBSTR( (IntPtr)(void*)bstrTmp );
	}
}

void	ModelServices::FireProgressNotification(DM_PROGRESS_NOTIFICATION_EVENT& in_event)
{
	AutoUseContext	apEC;
	USES_ERROR_HANDLING;
	THROW_ON_FAILURE( m_wpSvc->FireProgressNotification( apEC, &in_event) );
}


void	ModelServices::FireProgressNotification( TaskProgressNotification^ taskProgress, DM_PROGRESS_NOTIFICATION_ENUM notifCode, bool bSuccess)
{
	DM_PROGRESS_NOTIFICATION_EVENT	progEvent;
	memset(&progEvent, 0, sizeof(progEvent)) ;
	BSTR	bstrTmp;
	
	try
	{
		System::String^	strText = System::String::Format( CultureInfo::InvariantCulture, taskProgress->Format, taskProgress->Current, taskProgress->Total);
		
		progEvent.flags = DMPNF_USE_CCHTEXT | DMPNF_USE_JOBID | DMPNF_USE_TIMESTART;
		if( notifCode == DM_PROGRESS_NOTIFY_END )
		{
			progEvent.flags  |=	DMPNF_USE_HRESULT;
			progEvent.hResult = bSuccess ? S_OK : E_FAIL;
		}

		progEvent.NotifCode = notifCode;
		progEvent.nCurrent = taskProgress->Current;
		progEvent.nTotal = taskProgress->Total;

		progEvent.ulJobID = (UINT)taskProgress->m_jobID;
		progEvent.timeStart = taskProgress->m_timeStart;
		
		bstrTmp	=	(BSTR)(void*)System::Runtime::InteropServices::Marshal::StringToBSTR( strText );
		progEvent.cchText = strText->Length;
		progEvent.pchText = bstrTmp;

		FireProgressNotification( progEvent );

		// Copy the fields hat describe the current job
		taskProgress->m_jobID = progEvent.ulJobID;
		taskProgress->m_timeStart = progEvent.timeStart ;

	}
	finally
	{
		System::Runtime::InteropServices::Marshal::FreeBSTR( (IntPtr)(void*)bstrTmp );
	}

}




void	ModelServices::RenderModelStatisticsPMML(PMMLWriter^	writer)
{
	AutoUseContext	apEC;
	USES_ERROR_HANDLING;

	if( writer == nullptr || writer->m_wpContentHandler == NULL )
		throw gcnew System::ArgumentNullException();

	writer->MoveToContent();
	THROW_ON_FAILURE( m_wpSvc->RenderPMMLModelStatistics( apEC, writer->m_wpContentHandler) );
}

void	ModelServices::RenderMiningSchemaPMML(PMMLWriter^	writer)
{
	AutoUseContext	apEC;
	USES_ERROR_HANDLING;

	if( writer == nullptr || writer->m_wpContentHandler == NULL )
		throw gcnew System::ArgumentNullException();

	writer->MoveToContent();
	THROW_ON_FAILURE( m_wpSvc->RenderPMMLMiningSchema( apEC, writer->m_wpContentHandler) );
}

void	ModelServices::RenderModelCreationFlagsPMML(PMMLWriter^	writer)
{
	AutoUseContext	apEC;
	USES_ERROR_HANDLING;

	if( writer == nullptr || writer->m_wpContentHandler == NULL )
		throw gcnew System::ArgumentNullException();

	writer->MoveToContent();
	THROW_ON_FAILURE( m_wpSvc->RenderPMMLModelCreationFlags( apEC, writer->m_wpContentHandler) );
}

System::String^	ModelServices::FindNodeCaption(System::String ^nodeUniqueName)
{
	AutoUseContext	apEC;
	USES_ERROR_HANDLING;

	CComPtr<IDMContentMap>	spContentMap;
	

	CComPtr<IDMStringHandler>	spStringHandler;
	DMString*	pStrNUN = NULL;
	DMString*	pStrCaption = NULL;
	BSTR bstrTmp = NULL;

	if( nodeUniqueName == nullptr || nodeUniqueName->Length == 0 )
		return String::Empty;

	try
	{

		// Get the string handler
		THROW_ON_FAILURE( apEC->GetStringHandler(&spStringHandler) );
		// Create a new Handle
		THROW_ON_FAILURE( spStringHandler->CreateNewStringHandle(&pStrNUN) );

		
		int	length	=	0;
		bstrTmp = (BSTR)(void*)System::Runtime::InteropServices::Marshal::StringToBSTR( nodeUniqueName );
		length	=	nodeUniqueName->Length;
		
		THROW_ON_FAILURE( spStringHandler->CopyBufferToHandle( pStrNUN, bstrTmp, length) );


		THROW_ON_FAILURE( m_wpSvc->GetContentMap( apEC, &spContentMap ));

		THROW_ON_FAILURE( spContentMap->FindNodeCaption(pStrNUN, &pStrCaption) );
	
		if( (CURRENT_STATUS != S_OK) ||
			(pStrCaption == NULL) )
			return String::Empty;

		const WCHAR*	lpwszText = NULL;
		UINT ulTextLength = 0;
		THROW_ON_FAILURE( spStringHandler->GetConstStringFromHandle(pStrCaption, &lpwszText, &ulTextLength) );

		String^ caption	=	gcnew System::String( lpwszText, 0, ulTextLength );

		return caption;

	}
	finally
	{
		if( bstrTmp != NULL )
		{
			System::Runtime::InteropServices::Marshal::FreeBSTR( (IntPtr)(void*)bstrTmp );
		}
		if( spStringHandler && pStrNUN)
		{
			spStringHandler->DestroyStringHandle( pStrNUN );
		}
	}
}


